﻿using Newtonsoft.Json;

namespace Ocelot.Admin.Api.Application
{
    public class ProjectService : IProjectService, ITransient
    {
        private readonly SqlSugarScopeProvider _sqlserverDB;
        private readonly IRouteCacheService _routeCacheService;

        public ProjectService(ISqlSugarClient db, IRouteCacheService routeCacheService)
        {
            _sqlserverDB = db.AsTenant().GetConnectionScope(DatabaseConfigIdConst.OcelotSettings);
            _routeCacheService = routeCacheService;
        }

        #region 查询

        /// <summary>
        /// 查询项目信息
        /// </summary>
        /// <returns></returns>
        public async Task<List<Project>> GetProjectsAsync()
        {
            return await _sqlserverDB.Queryable<Project>().With(SqlWith.NoLock)
                .Includes(o => o.Routes, route => route.RouteHostPorts)
                .Includes(o => o.Routes, route => route.RouteProperties)
                .OrderByDescending(o => o.OrderIndex)
                .Where(o => o.Enabled == true).ToListAsync();
        }

        /// <summary>
        /// 查询所有可用的项目
        /// </summary>
        /// <returns></returns>
        public async Task<List<int>> GetAllEnabledProjectIdsAsync()
        {
            return await _sqlserverDB.Queryable<Project>().With(SqlWith.NoLock)
                .Where(o => o.Enabled == true).Select(o => o.Id).ToListAsync();
        }

        /// <summary>
        /// 分页查询项目信息
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<SqlSugarPagedList<Project>> GetPageProjectAsync(PageProjectRequest request)
        {
            var enabled = request.Enabled.HasValue && request.Enabled.Value == 1;
            DateTime unixEpoch = new DateTime(1970, 1, 1);
            return await _sqlserverDB.Queryable<Project>().With(SqlWith.NoLock)
                .WhereIF(!string.IsNullOrWhiteSpace(request.SearchKey),
                    o => o.ProjectName.Contains(request.SearchKey))
                .WhereIF(request.UpdateTime != null && request.UpdateTime.Length > 1,
                    o => o.UpdateTime >= request.UpdateTime.Min().Subtract(unixEpoch).TotalSeconds
                         && o.UpdateTime < request.UpdateTime.Max().AddDays(1).Subtract(unixEpoch).TotalSeconds)
                .WhereIF(request.Enabled.HasValue,
                    o => o.Enabled == enabled)
                .WhereIF(request.CreateTime != null && request.CreateTime.Length > 1,
                    o => o.CreateTime >= request.CreateTime.Min().Subtract(unixEpoch).TotalSeconds
                         && o.CreateTime < request.CreateTime.Max().AddDays(1).Subtract(unixEpoch).TotalSeconds)
                .OrderByDescending(o => o.Id)
                .ToPagedListAsync(request.Current, request.PageSize);
        }

        #endregion

        #region 新增

        /// <summary>
        /// 新增项目信息
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<string> InsertProjectAsync(InsertProjectRequest request)
        {
            var Project = request.Adapt<Project>();
            Project.Enabled = false;
            var isExist = await _sqlserverDB.Queryable<Project>()
                .FirstAsync(x => x.ProjectCode.Equals(request.ProjectCode));
            if (isExist != null)
            {
                throw Oops.Oh(ErrorCodes.INSERT_PROJECT_FAIL_EXISTCODE)
                    .StatusCode((int)ErrorCodes.INSERT_PROJECT_FAIL_EXISTCODE);
            }
            Project.Servers = request.Servers ;
            var insertResult = await _sqlserverDB.Insertable(Project).ExecuteCommandAsync();
            if (insertResult > 0)
            {
                return "新增项目成功";
            }
            else
            {
                throw Oops.Oh(ErrorCodes.INSERT_PROJECT_FAIL).StatusCode((int)ErrorCodes.INSERT_PROJECT_FAIL);
            }
        }

        #endregion

        #region 编辑

        /// <summary>
        /// 更新项目信息
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<string> UpdateProjectAsync(UpdateProjectRequest request)
        {
            var Project = request.Adapt<Project>();
            var isExist = await _sqlserverDB.Queryable<Project>()
                .FirstAsync(x => x.ProjectCode.Equals(request.ProjectCode) && !x.Id.Equals(request.Id));
            if (isExist != null)
            {
                throw Oops.Oh(ErrorCodes.INSERT_PROJECT_FAIL_EXISTCODE)
                    .StatusCode((int)ErrorCodes.INSERT_PROJECT_FAIL_EXISTCODE);
            }
            Project.Servers = request.Servers ;
            var result = await _sqlserverDB.Updateable(Project)
                .IgnoreColumns(it => new { it.CreateTime, it.Enabled })
                .ExecuteCommandHasChangeAsync();
            if (result)
            {
                return "编辑项目成功";
            }
            else
            {
                throw Oops.Oh(ErrorCodes.UPDATE_PROJECT_FAIL).StatusCode((int)ErrorCodes.UPDATE_PROJECT_FAIL);
            }
        }

        /// <summary>
        /// 启用或禁用项目信息
        /// </summary>
        /// <param name="projectId">项目Id</param>
        /// <param name="enabled">是否有效</param>
        /// <returns></returns>
        public async Task<string> PatchProjectAsync(int projectId, bool enabled)
        {
            var result = await _sqlserverDB.Updateable<Project>()
                .SetColumns(it => new Project()
                    { Enabled = enabled, UpdateTime = DateTimeOffset.Now.ToUnixTimeSeconds() })
                .Where(it => it.Id == projectId)
                .ExecuteCommandHasChangeAsync();
            if (result)
            {
                return $"{(enabled ? "启动" : "禁用")}项目成功";
            }
            else
            {
                var errorCode = enabled ? ErrorCodes.ENABLE_PROJECT_FAIL : ErrorCodes.DISABLE_PROJECT_FAIL;
                throw Oops.Oh(errorCode).StatusCode((int)errorCode);
            }
        }

        #endregion

        #region 删除

        /// <summary>
        /// 删除项目信息
        /// </summary>
        /// <param name="projectId">项目Id</param>
        /// <returns></returns>
        public async Task<string> DeleteProjectAsync(int projectId)
        {
            var result = await _sqlserverDB.Deleteable<Project>()
                .Where(it => it.Id == projectId)
                .ExecuteCommandHasChangeAsync();
            if (result)
            {
                return $"删除项目成功";
            }
            else
            {
                throw Oops.Oh(ErrorCodes.DELETE_PROJECT_FAIL).StatusCode((int)ErrorCodes.DELETE_PROJECT_FAIL);
            }
        }

        #endregion
    }
}